package tr.edu.yildiz.ce.dap.appagent.manager;

import java.nio.channels.SelectionKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import tr.edu.yildiz.ce.dap.appagent.process.DeploymentProcess;
import tr.edu.yildiz.ce.dap.appagent.process.ListenerProcess;
import tr.edu.yildiz.ce.dap.appagent.process.PromptProcess;
import tr.edu.yildiz.ce.dap.appagent.process.ProxyConnectionController;
import tr.edu.yildiz.ce.dap.appagent.process.RegistrationProcess;
import tr.edu.yildiz.ce.dap.appagent.process.base.AbstractProcess;
import tr.edu.yildiz.ce.dap.appagent.util.AgentProperties;

public class AgentProcessManager implements Runnable{
	
	List<AbstractProcess> processList = new ArrayList<AbstractProcess>();
	BundleContext context;
	Timer proxyTimer;
	ListenerProcess listenerProcess;
	
	volatile boolean needsRegistration = true;
	
	class ProxyTimerTask extends TimerTask {
		
		ProxyConnectionController pcc;
		
		public ProxyTimerTask(ProxyConnectionController pcc) {
			this.pcc = pcc;
		}
		
		@Override
		public void run() {
			pcc.run();
		}
		
	}
	
	public AgentProcessManager(BundleContext context) {
		this.context = context;
	}
	
	
	public List<AbstractProcess> getProcessList() {
		return processList;
	}
	
	public BundleContext getContext() {
		return context;
	}

	private boolean workOffline(){
		String offline = System.getProperty("offline");
		if (offline == null)
			return false;
		return offline.equalsIgnoreCase("true");
	}
	
	@Override
	public void run() {
		while (true){
			if (!workOffline()){
				createRegistrationProcess(	AgentProperties.getInstance().getProxyMcastAddress(), 
						AgentProperties.getInstance().getProxyPort());
				proxyTimer = new Timer();
				proxyTimer.schedule(new ProxyTimerTask(	new ProxyConnectionController(	this, 
																					  	AgentProperties.getInstance().getProxyMcastAddress(), 
																					  	AgentProperties.getInstance().getProxyPort())), 
									500,500);
			}else 
				needsRegistration = false;
			String promptType = AgentProperties.getInstance().getPrompt();
			if (promptType != null){
				createPromptCommand(promptType);
			}
			while (!needsRegistration){
				try {
					Thread.currentThread().sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	public void setNeedsRegistration(boolean needsRegistration) {
		this.needsRegistration = needsRegistration;
	}
	
	public void createListenerProcess(Integer port){
		listenerProcess = new ListenerProcess(this,port);
		needsRegistration = false;
		new Thread(listenerProcess).start();
	}
	
	public void createProxyCommand(String xml,SelectionKey skey){
		DeploymentProcess dProcess = new DeploymentProcess(this,skey,xml);
		new Thread(dProcess).start();
	}
	
	public void createPromptCommand(String promptType){
		if (promptType.equalsIgnoreCase("PromptProcess")){
			PromptProcess pProcess = new PromptProcess(this);
			new Thread(pProcess).start();
		}
	}
	
	public void createRegistrationProcess(String multicastAddress,Integer port){
		RegistrationProcess dProcess = new RegistrationProcess(this,multicastAddress,port);
		dProcess.run();
	}
	
	public Object getService(String className){
		ServiceReference sReference = null;
		do{
			sReference = context.getServiceReference(className);
			if (sReference == null){
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("service is not initialized yet : " + className);
			}
		}while(sReference == null);
	    return context.getService(sReference);
	}
	
	public void stop() {
		if (proxyTimer != null)
			proxyTimer.cancel();
		if (listenerProcess != null)
			listenerProcess.stop();
		
	}
	
}
